﻿using DrawTools.Serialize;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace DrawTools.Tools
{
    /// <summary>
    /// 文本
    /// </summary>
    [SerializerType(typeof(DrawTextSerializer))]
    public sealed class TextDrawTool : DrawGeometryBase
    {
        #region 字段

        private Thickness padding;
        private TextBox textBox;
        private Point startPoint, textPoint;
        private double minWidth, minHeight, actualWidth, actualHeight;

        public bool ReadOnly { get; set; } = false;

        public override string Text
        {
            get => textBox?.Text;
            set
            {
                if (textBox == null) return;
                textBox.Text = value;
            }
        }

        public override Pen Pen => new Pen(drawingCanvas.Brush, 1);

        #endregion 字段

        public TextDrawTool(DrawingCanvas drawingCanvas) : base(drawingCanvas)
        {
            DrawingToolType = DrawToolType.Text;

            // 准备要处理的事件
            CanTouchDown = true;
        }

        #region 鼠标键盘事件

        public override bool OnTouchDown(int touchId, Point point)
        {
            TouchId = touchId;
            lock (this)
            {
                if (textBox == null)
                {
                    drawingCanvas.AddWorkingDrawTool(this);
                    drawingCanvas.AddVisual(this);
                    startPoint = point;
                    padding = new Thickness(Pen.Thickness * 3);
                    minWidth = minHeight = FontSize * 2 + Pen.Thickness * 8;
                    AddTextBox();
                }
                else if (!IsFinish && drawingCanvas.GetVisual(point) is TextDrawTool textDrawTool && textDrawTool != this)
                {
                    textDrawTool.TouchId = TouchId;
                    textDrawTool.Edit();
                    IsFinish = true;
                    CanTouchDown = false;
                }
                else OnTextBoxLostFocus(null, null);

                return true;
            }
        }

        #endregion 鼠标键盘事件

        #region 绘图事件

        public override void Draw()
        {
            var dc = RenderOpen();
            dc.DrawRectangle(Brushes.Transparent, null, selectRect);
            dc.DrawGeometry(Pen.Brush, null, geometry);
            dc.Close();
        }

        public override bool Select(Point point)
        {
            return selectRect.Contains(point);
        }

        public override bool Select(Geometry select)
        {
            var rect = select.GetRenderBounds(drawingCanvas.SelectPen);
            return selectRect.IntersectsWith(rect);
        }

        protected override Rect GetRenderBounds()
        {
            return selectRect;
        }

        public override void Move(double dx, double dy)
        {
            startPoint.X += dx;
            startPoint.Y += dy;

            selectRect.Location = startPoint;

            base.Move(dx, dy);
        }

        public override void Edit()
        {
            if (Mode == 2)
                return;

            Mode = 2;

            drawingCanvas.AddWorkingDrawTool(this);

            IsFinish = false;
            CanTouchDown = true;
            CanEdit = false;

            AddTextBox();
        }

        #endregion 绘图事件

        #region 私有方法

        private void AddTextBox()
        {
            textBox = new TextBox
            {
                Background = Brushes.Transparent,
                Foreground = Pen.Brush,
                BorderThickness = new Thickness(),
                Padding = padding,
                FontFamily = new FontFamily("Microsoft YaHei UI,Tahoma"),
                FontSize = FontSize,
                Style = null,
                FocusVisualStyle = null,
                AcceptsReturn = true,
                AcceptsTab = true,
                MinWidth = minWidth,
                MinHeight = minHeight,
                Text = Text,
                IsReadOnly = ReadOnly
            };

            if (textBox.IsReadOnly == true)
            {
                textBox.MinWidth = 100;
                textBox.MinHeight = 20;
                textBox.Background = new SolidColorBrush(Colors.Red);
                textBox.BorderBrush = Brushes.Green;
                textBox.BorderThickness = new Thickness(1);
            }

            textBox.SelectionStart = textBox.Text.Length;

            Canvas.SetLeft(textBox, startPoint.X + Pen.Thickness);
            Canvas.SetTop(textBox, startPoint.Y + Pen.Thickness);
            textBox.Loaded += OnTextBoxLoaded;
            textBox.SizeChanged += OnTextBoxSizeChanged;
            textBox.LostFocus += OnTextBoxLostFocus;
            textBox.Visibility = Visibility.Visible;

            drawingCanvas.Children.Add(textBox);
        }

        private void OnTextBoxLoaded(object sender, RoutedEventArgs e)
        {
            textBox.Focus();

            var ch = (ContentControl)textBox.Template.FindName("PART_ContentHost", textBox);

            var tf = ((Visual)ch.Content).TransformToAncestor(textBox);
            var offset = tf.Transform(new Point());

            textPoint.X = startPoint.X + offset.X + Pen.Thickness;
            textPoint.Y = startPoint.Y + offset.Y + Pen.Thickness;
        }

        private void OnTextBoxSizeChanged(object sender, SizeChangedEventArgs e)
        {
            actualWidth = e.NewSize.Width;
            actualHeight = e.NewSize.Height;

            selectRect = new Rect(startPoint, new Size(actualWidth + Pen.Thickness * 2, actualHeight + Pen.Thickness * 2));

            var dc = RenderOpen();
            dc.DrawRectangle(Brushes.Transparent, Pen, selectRect);
            dc.Close();
        }

        public void SetText(string text)
        {
            if (textBox == null) return;
            textPoint.X = startPoint.X + Pen.Thickness;
            textPoint.Y = startPoint.Y + Pen.Thickness;
            textBox.Margin = new Thickness(textPoint.X, textPoint.Y, 0, 0);
            textBox.Text = text;
        }

        public void AddText(string text)
        {
            if (textBox == null) return;
            textBox.Text += text;
        }

        private void OnTextBoxLostFocus(object sender, RoutedEventArgs e)
        {
            textBox.Loaded -= OnTextBoxLoaded;
            textBox.SizeChanged -= OnTextBoxSizeChanged;
            textBox.LostFocus -= OnTextBoxLostFocus;

            drawingCanvas.Focus();
            drawingCanvas.Children.Remove(textBox);

            if (string.IsNullOrWhiteSpace(textBox.Text))
                drawingCanvas.DeleteVisual(this);
            else
            {
                Text = textBox.Text;

                var formattedText = GetFormattedText();

                geometry = formattedText.BuildGeometry(textPoint).GetFlattenedPathGeometry();
                Draw();
            }

            drawingCanvas.DeleteWorkingDrawTool(this);

            IsFinish = true;
            CanTouchDown = false;
            CanEdit = true;

            textBox = null;
        }

        #endregion 私有方法
    }
}